package logic

import (
	"common/global"
	"common/utils"
	"context"
	"equipment_server/model"
	equipment "equipment_server/proto"
	"errors"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"

	"time"
)

type Hr struct {
	Id          string    `json:"_id" bson:"_id"`
	EquipmentId string    `json:"equipment_id" bson:"equipment_id"` //设备ID
	HeartRate   int       `json:"heart_rate" bson:"heart_rate"`     //心率
	TimesTamp   time.Time `json:"timestamp" bson:"timestamp"`       //时间
}
type Bp struct {
	Id          string    `json:"_id" bson:"_id"`
	EquipmentId string    `json:"equipment_id" bson:"equipment_id"` //设备ID
	Systolic    int       `json:"systolic" bson:"systolic"`         //高压
	Diastolic   int       `json:"diastolic" bson:"diastolic"`       //低压
	Timestamp   time.Time `json:"timestamp" bson:"timestamp"`       //时间
}

func (e *EquipmentServer) ObtainHealthData(ctx context.Context, req *equipment.ObtainHealthDataRequest) (*equipment.ObtainHealthDataResponse, error) {
	// 1. 检查用户是否绑定了设备
	bindingsCollection := global.MonGoDatabase.Collection("device_bindings")
	filterUserBinding := bson.M{
		"user_id": req.UserID,
	}

	var userBinding model.DeviceBinding
	err := bindingsCollection.FindOne(ctx, filterUserBinding).Decode(&userBinding)
	if err != nil {
		if errors.Is(err, mongo.ErrNoDocuments) {
			// 用户未绑定设备
			return nil, errors.New("您尚未绑定设备，请先绑定设备后再查看健康数据")
		}
		// 其他数据库错误
		return nil, errors.New("查询设备绑定信息失败")
	}

	// 2. 使用绑定的设备ID查询健康数据
	var filterHR = map[string]interface{}{"equipment_id": userBinding.DeviceID}
	var filterBP = map[string]interface{}{"equipment_id": userBinding.DeviceID}

	//如果有查询时间  则拼接查询时间  没有则查询所有 （查询时间的校验也在这校验）
	if req.StartDate != "" && req.EndDate != "" {
		startDate, err := time.Parse("2006-01-02", req.StartDate)
		if err != nil {
			return nil, errors.New("时间解析错误")
		}
		endDate, err := time.Parse("2006-01-02", req.EndDate)
		if err != nil {
			return nil, errors.New("时间解析错误")
		}
		if startDate.After(endDate) {
			return nil, errors.New("起始时间不能晚于结束时间")
		}
		//校验1：只能查询一个月间隔的数据
		if endDate.Sub(startDate) > 31*24*time.Hour {
			return nil, errors.New("只能查询一个月内的数据")
		}
		// 校验2：只能查询一年的数据（起始时间不能早于当前时间往前推一年）
		oneYearAgo := time.Now().AddDate(-1, 0, 0)
		if startDate.Before(oneYearAgo) {
			return nil, errors.New("只能查询最近一年的数据")
		}
		filterHR["timestamp"] = map[string]interface{}{"$gte": startDate, "$lte": endDate.Add(24 * time.Hour)}
		filterBP["timestamp"] = map[string]interface{}{"$gte": startDate, "$lte": endDate.Add(24 * time.Hour)}
	}
	//先处理心率数据
	//先查询
	hrColl := global.MonGoDatabase.Collection("heart_rate")
	hrRes, err := utils.MongoGetFind(ctx, hrColl, filterHR)
	if err != nil {
		return nil, err
	}
	defer hrRes.Close(ctx)
	var heartDataClean []Hr
	var toDeleteHR []time.Time
	//这里查询出来数据
	for hrRes.Next(ctx) {
		var d Hr
		err = hrRes.Decode(&d)
		if err != nil {
			panic(err)
		}
		if d.HeartRate >= 30 && d.HeartRate <= 220 {
			heartDataClean = append(heartDataClean, d)
		} else {
			toDeleteHR = append(toDeleteHR, d.TimesTamp)
		}
	}
	//这里处理展示数据
	var heartList []*equipment.HeartRate
	for _, hr := range heartDataClean {
		timeList := hr.TimesTamp.Format(time.DateTime)
		heartList = append(heartList, &equipment.HeartRate{
			HeartRate: int64(hr.HeartRate),
			Timestamp: timeList,
		})
	}
	//这里删除心率的脏数据
	for _, ts := range toDeleteHR {
		utils.DelMongoWhereSearchConditions(ctx, hrColl, map[string]interface{}{"equipment_id": userBinding.DeviceID, "timestamp": ts})
	}
	//再处理血压数据
	//先查询
	bpColl := global.MonGoDatabase.Collection("blood_pressure")
	bpRes, err := utils.MongoGetFind(ctx, bpColl, filterBP)
	if err != nil {
		return nil, err
	}
	defer hrRes.Close(ctx)
	var bpDataClean []Bp
	var toDeleteBp []time.Time
	//这里查询出来数据
	for bpRes.Next(ctx) {
		var d Bp
		err = bpRes.Decode(&d)
		if err != nil {
			panic(err)
		}
		if d.Systolic >= 40 && d.Systolic <= 250 && d.Diastolic >= 30 && d.Diastolic <= 150 && d.Systolic > d.Diastolic {
			bpDataClean = append(bpDataClean, d)
		} else {
			toDeleteBp = append(toDeleteBp, d.Timestamp)
		}
	}
	//这里处理展示数据
	var bpList []*equipment.BloodPressure
	for _, bp := range bpDataClean {
		timeList := bp.Timestamp.Format(time.DateTime)
		bpList = append(bpList, &equipment.BloodPressure{
			Diastolic: int64(bp.Diastolic),
			Systolic:  int64(bp.Systolic),
			Timestamp: timeList,
		})
	}
	//这里删除血压的脏数据
	for _, ts := range toDeleteBp {
		utils.DelMongoWhereSearchConditions(ctx, bpColl, map[string]interface{}{"equipment_id": userBinding.DeviceID, "timestamp": ts})
	}
	return &equipment.ObtainHealthDataResponse{
		AllBloodPressure: bpList,
		AllHeartRate:     heartList,
	}, err
}
